package com.harry.decoupling.impl.proxy;

import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.stream.Stream;

import org.springframework.stereotype.Service;

import com.harry.basis.BaseGeneric;
import com.harry.basis.BasePoEntity;
import com.harry.decoupling.defi.module.GenericSrv;
import com.harry.decoupling.defi.proxy.GenericSrvProxy;
import com.harry.utility.query.InnerCriteria;
import com.harry.utility.query.PageCount;

@Service
public class GenericProxyImplSrv implements GenericSrvProxy {

	@Override
	public <T extends BasePoEntity> T one(Class<T> entityClass, String id) throws Exception {
		return (T) impl(entityClass).one(id);
	}

	@SuppressWarnings("unchecked")
	@Override
	public <T extends BasePoEntity> T save(T t) throws Exception {
		Object impl = impl(t.getClass());
		Method saveMethod = Stream.of(impl.getClass().getMethods()).filter(m -> m.getName().equals("save")).findFirst().get();
		return (T) saveMethod.invoke(impl, t);
	}

	@Override
	public <T extends BasePoEntity> List<T> query(Class<T> entityClass, InnerCriteria criteria, PageCount page) throws Exception {
		return impl(entityClass).queryEntitiesByCriteriaWithPage(criteria, page);
	}

	@Override
	public <T extends BasePoEntity> int updateByCriteria(Class<T> entityClass, Map<String, Object> params, InnerCriteria cri) throws Exception {
		return impl(entityClass).updateByCriteria(params, cri);
	}

	@Override
	public <T extends BasePoEntity> int deleteByCriteria(Class<T> entityClass, InnerCriteria cri) throws Exception {
		return impl(entityClass).deleteByCriteria(cri);
	}

	@Override
	public <T extends BasePoEntity> int countByCriteria(Class<T> entityClass, InnerCriteria criteria) throws Exception {
		return impl(entityClass).countByCriteria(criteria);
	}

	@Override
	public <T extends BasePoEntity> T findByName(Class<T> entityClass, String name) throws Exception {
		return (T) impl(entityClass).findByName(name);
	}

	@Override
	public <T extends BasePoEntity> void delete(Class<T> entClass, T obj) throws Exception {
		impl(entClass).delete(obj);
	}

	@Override
	public <T> T exec(Callable<T> call) throws Exception {
		return call.call();
	}

	@SuppressWarnings("unchecked")
	private <T extends BasePoEntity> GenericSrv<T> impl(Class<T> entityClass) throws Exception {
		return (GenericSrv<T>) BaseGeneric.beanOf(GenericSrv.class, entityClass);
	}
}
